package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

/**
 * go中的tag 字段上还可以额外再加一个属性，用反引号（Esc键下面的那个键）包含的字符串，称之为 Tag，也就是标签
 */
func main() {
	viewTag()
	stu := Student{Name: "张三", School: "广州中学"}
	Print(stu)
}

/**
 * @param
 */
func viewTag() {
	p1 := Person{
		Name: "Jack",
		Age:  22,
	}

	data1, err := json.Marshal(p1)
	if err != nil {
		panic(err)
	}

	// p1 没有 Addr，就不会打印了
	fmt.Printf("%s\n", data1)

	// ================

	p2 := Person{
		Name: "Jack",
		Age:  22,
		Addr: "China",
	}

	data2, err := json.Marshal(p2)
	if err != nil {
		panic(err)
	}

	// p2 则会打印所有
	fmt.Printf("%s\n", data2)
}

func Print(obj interface{}) error {
	// 取 Value
	v := reflect.ValueOf(obj)

	// 解析字段
	for i := 0; i < v.NumField(); i++ {

		// 取tag
		field := v.Type().Field(i)
		tag := field.Tag

		// 解析label 和 default
		label := tag.Get("label")
		defaultValue := tag.Get("default")
		fmt.Println("defaultValue:" + defaultValue)

		value := fmt.Sprintf("%v", v.Field(i))

		if value == "" || value == "0" {
			// 如果没有指定值，则用默认值替代
			value = defaultValue
		}

		fmt.Println(label + value)
	}

	return nil
}

/**
 * 正常结构体
 */
// type Person struct  {
// 	Name string
// 	Age int
// 	Addr string
// }

/**
 * 带tag正常结构体 此处的json可以与java中的jackson框架的JsonProperty
 */
type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
	Addr string `json:"addr,omitempty"`
}

/**
 * 定义学生结构体
 */
type Student struct {
	Name   string `label:"name is:"`
	School string `label:"school is:"`
	Grade  int    `label:"grade is:" default:"3"`
}
